﻿#include <QDesktopWidget>
#include <QComboBox>
#include <QLabel>
#include <QFileDialog>
#include <QKeyEvent>
#include <QRadioButton>
#include <QHBoxLayout>
#include <QList>
#include <QUrl>
#include <QMimeData>
#include <QMessageBox>

#include <setting/optiondialog.h>

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "dataview.h"
#include "insightview.h"
#include "udfmodel.h"
MainWindow::MainWindow(QWidget* parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    m_nTab = 0;
    m_nView = 0;
    setGeometry(QStyle::alignedRect(
                    Qt::LeftToRight,
                    Qt::AlignCenter,
                    QSize(800, 600),
                    qApp->desktop()->availableGeometry()
                    ));

    QIcon icon(":images/CodeReview.png");
    setWindowIcon(icon);
    insightView = new InsightView(this);
    m_pChartView = new ChartView(this);
    m_pChartView->hide();

    insightView->setAcceptDrops(false);


    addDockWidget(Qt::RightDockWidgetArea, insightView);

    createActions();
    createMenus();
    createToolBar();
    createStatusBar();

    tab = new QTabWidget(this);
    tab->setTabsClosable(true);
    tab->setLayout(new QHBoxLayout());
    setCentralWidget(tab);

    connect(tab, SIGNAL(tabCloseRequested(int)), SLOT(tabClosed(int)));
    connect(tab, SIGNAL(currentChanged(int)), SLOT(tabChanged(int)));

    setAcceptDrops(true);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::tabClosed(int index)
{
    if (DataView* view = dynamic_cast<DataView*>(tab->widget(index))) {
        if (view->HexEditisModified() || view->IstempFile()) {
            QMessageBox box(QMessageBox::Warning, tr("warning"), tr("the file is chaged,save or no?"));
            box.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
            box.setButtonText(QMessageBox::Yes, QString(tr("Yes")));
            box.setButtonText(QMessageBox::No, QString(tr("No")));
            int ret = box.exec();
            switch (ret) {
            case QMessageBox::Yes:
                view->savaAs();
                break;
            case QMessageBox::No:
                break;
            }
        }
        view->deletetempFile();
    }
    tab->removeTab(index);
}

void MainWindow::tabChanged(int index)
{
    DataView* view = dynamic_cast<DataView*>(tab->widget(index));
    chartViewHide();
    if (view == 0)
        return;
    m_nTab = index;
    qint64 pos = view->cursorPosition();
    addressChanged(view, pos);
    switch (view->getViewMode()) {
    case DataView::Hex:
        ui->actionHexView->setChecked(true);
        break;
    case DataView::Frame:
        ui->actionFrameView->setChecked(true);
        break;
    case DataView::PDXP:
        ui->actionPDXPView->setChecked(true);
        chartViewShow();
        m_nView = 2;
        break;
    case DataView::UDF:
        ui->actionUDFView->setChecked(true);
        chartViewShow();
        m_nView = 1;
        break;
    }
}

void MainWindow::addressChanged(DataView* view, qint64 address)
{
    addressLabel->setText(QString("%1").arg(address));
    QByteArray array = view->dataAt(address, 64);
    insightView->setData(array);
}

void MainWindow::viewGroupTriggered(QAction* action)
{
    if (DataView* view = dynamic_cast<DataView*>(tab->currentWidget())) {
        if (action == ui->actionFixedView) {
            view->toggleFixedView();
        } else if (action == ui->actionHexView) {
            view->toggleHexView();
            chartViewHide();
        }
        else if (action == ui->actionFrameView) {
            view->toggleFrameView();
            chartViewHide();
        }
        else if (action == ui->actionUDFView) {
            view->toggleUDFView();
            chartViewShow();
            m_nView = 1;
        }
        else if (action == ui->actionPDXPView) {
            view->togglePDXPView();
            chartViewShow();
            m_nView = 2;
        }
    }
}

void MainWindow::find(const QString& text)
{
    findBox->setEnabled(false);

    if (tab->count() > 0) {
        QByteArray ba = QByteArray::fromHex(text.toLatin1());
        if (ba.length()) {
            if (DataView* view = dynamic_cast<DataView*>(tab->currentWidget())) {
                qint64 from = view->cursorPosition() / 2;
                if (findForward->isChecked())
                    view->indexOf(ba, from);
                else
                    view->lastIndexOf(ba, from);
            }
        }
    }

    findBox->setEnabled(true);
    findBox->setFocus();
}

QMap<QString, int> MainWindow::openFiles()
{
    QMap<QString, int> files;
    for (int i = 0; i < tab->count(); i++) {
        if (DataView* view = dynamic_cast<DataView*>(tab->widget(i))) {
            files.insert(view->getFile().fileName(), i);
        }
    }
    return files;
}

void MainWindow::createActions()
{
    ui->actionSaveAs->setShortcut(QKeySequence::SaveAs);
    connect(ui->actionSaveAs, SIGNAL(triggered(bool)), this, SLOT(saveAsTriggered()));

    ui->actionUndo->setShortcut(QKeySequence::Undo);
    connect(ui->actionUndo, SIGNAL(triggered(bool)), this, SLOT(undoTriggered()));

    ui->actionRedo->setShortcut(QKeySequence::Redo);
    connect(ui->actionRedo, SIGNAL(triggered(bool)), this, SLOT(redoTriggered()));

    viewGroup = new QActionGroup(this);
    viewGroup->addAction(ui->actionFixedView);
    viewGroup->addAction(ui->actionHexView);
    viewGroup->addAction(ui->actionFrameView);
    viewGroup->addAction(ui->actionUDFView);
    viewGroup->addAction(ui->actionPDXPView);
    ui->actionHexView->setChecked(true);
    connect(viewGroup, SIGNAL(triggered(QAction*)), this, SLOT(viewGroupTriggered(QAction*)));
}

void MainWindow::createMenus()
{
    ui->actionOpen->setIconVisibleInMenu(true);
    ui->actionExit->setIconVisibleInMenu(true);
    ui->actionFind->setIconVisibleInMenu(true);

    connect(ui->actionAboutQt, SIGNAL(triggered()), qApp, SLOT(aboutQt()));

    contextAction = ui->menu_View->addMenu(createPopupMenu());
    contextAction->setText(tr("Docked Windows"));
    ui->menu_View->insertSeparator(contextAction);
}

void MainWindow::createToolBar()
{
    findBox = new QComboBox();
    findBox->setAcceptDrops(false);
    findBox->setEditable(true);
    findBox->setMinimumWidth(240);
    findBox->installEventFilter(this);
    //    connect(findBox, SIGNAL(currentIndexChanged(QString)), SLOT(find(QString)));
    ui->mainToolBar->addWidget(findBox);

    findForward = new QRadioButton(tr("Forward"));
    findForward->setChecked(true);
    ui->mainToolBar->addWidget(findForward);
    findBackward = new QRadioButton(tr("Backward"));
    ui->mainToolBar->addWidget(findBackward);
}

void MainWindow::createStatusBar()
{
    offsetLabel = new QLabel(tr("Offset:"));
    statusBar()->addPermanentWidget(offsetLabel);

    addressLabel = new QLabel();
    addressLabel->setMinimumWidth(80);
    statusBar()->addPermanentWidget(addressLabel);
    //    addressLabel->setAlignment(Qt::AlignLeft);
    //    addressLabel->setMinimumSize(addressLabel->sizeHint());

    //    statusBar()->addWidget(addressLabel);
}

void MainWindow::openFile(const QString& name)
{
    if (!name.isEmpty()) {
        m_sFile = name;
        QString nameOnly = QFileInfo(name).fileName();
        QMap<QString, int> fileMap = openFiles();
        QMap<QString, int>::iterator it = fileMap.find(name);
        if (it != fileMap.end()) {
            tab->setCurrentIndex(it.value());
        }
        else {
            DataView* view = new DataView(name, tab);
            //            connect(ui->actionSaveAs, SIGNAL(triggered(bool)), view, SLOT(savaAs()));
            connect(view, SIGNAL(viewAddressChanged(DataView*, qint64)), SLOT(addressChanged(DataView*, qint64)));
            connect(view, SIGNAL(openTempFile(QString)), this, SLOT(openTempFile(QString)));
            tab->setCurrentIndex(tab->addTab(view, nameOnly));
        }
    }
}

void MainWindow::openTempFile(const QString& name)
{
    if (!name.isEmpty()) {
        m_sFile = name;
        QString nameOnly = QFileInfo(name).fileName();
        QMap<QString, int> fileMap = openFiles();
        QMap<QString, int>::iterator it = fileMap.find(name);
        if (it != fileMap.end()) {
            tab->setCurrentIndex(it.value());
        }
        else {
            DataView* view = new DataView(name, tab, true);
            //            connect(ui->actionSaveAs, SIGNAL(triggered(bool)), view, SLOT(savaAs()));
            connect(view, SIGNAL(viewAddressChanged(DataView*, qint64)), SLOT(addressChanged(DataView*, qint64)));
            connect(view, SIGNAL(openTempFile(QString)), this, SLOT(openTempFile(QString)));
            tab->setCurrentIndex(tab->addTab(view, nameOnly));
        }
    }
}

bool MainWindow::eventFilter(QObject* object, QEvent* event)
{
    if (object == findBox) {
        if (event->type() == QEvent::KeyPress) {
            if (QKeyEvent* keyEvent = dynamic_cast<QKeyEvent*>(event)) {
                if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) {
                    find(findBox->currentText());
                }
            }
        }
    }

    return false;
}

void MainWindow::chartViewHide()
{
    ui->actionBarChart->setEnabled(false);
    ui->actionLineChart->setEnabled(false);
    ui->actionSplineChart->setEnabled(false);
}

void MainWindow::chartViewShow()
{
    ui->actionBarChart->setEnabled(true);
    ui->actionLineChart->setEnabled(true);
    ui->actionSplineChart->setEnabled(true);
}

void MainWindow::dragEnterEvent(QDragEnterEvent* event)
{
    if (event->mimeData()->hasUrls())
        event->acceptProposedAction();
    else
        event->ignore();

}

void MainWindow::dropEvent(QDropEvent* event)
{
    const QMimeData* mineData = event->mimeData();
    if (mineData->hasUrls()) {
        QList<QUrl>urlList = mineData->urls();
        if (urlList.isEmpty())
            return;

        QString name = urlList.at(0).toLocalFile();
        openFile(name);
    }
}

void MainWindow::on_actionFind_triggered()
{
    if (ui->mainToolBar->isHidden())
        ui->mainToolBar->show();

    findBox->setFocus();
}

void MainWindow::on_actionFindNext_triggered()
{
    find(findBox->currentText());
}

void MainWindow::on_actionOpen_triggered()
{
    QString name = QFileDialog::getOpenFileName(this);

    openFile(name);
}

//void MainWindow::on_actionUDFView_triggered(bool checked)
//{
//	if (DataView* view = dynamic_cast<DataView*>(tab->currentWidget())) {
//		if (view->toggleUDFView(checked)) {
//			ui->actionPDXPView->setChecked(false);
//		}
//		else {
//			ui->actionUDFView->setChecked(false);
//		}
//	}
//}

//void MainWindow::on_actionPDXPView_triggered(bool checked)
//{
//	if (DataView* view = dynamic_cast<DataView*>(tab->currentWidget())) {
//		if (view->togglePDXPView(checked)) {
//			ui->actionUDFView->setChecked(false);
//		}
//		else {
//			ui->actionPDXPView->setChecked(false);
//		}
//	}
//}

//void MainWindow::on_actionFrameView_triggered(bool checked)
//{
//	if (DataView* view = dynamic_cast<DataView*>(tab->currentWidget())) {
//		if (view->toggleFrameView(true)) {
//			ui->actionPDXPView->setChecked(false);
//			ui->actionUDFView->setChecked(false);
//		}
//		else {
//			ui->actionFrameView->setChecked(false);
//		}
//	}
//}

void MainWindow::on_actionOptions_triggered()
{
    OptionDialog settings(this);
    settings.exec();
    if (DataView* view = dynamic_cast<DataView*>(tab->currentWidget())) {
        view->HexEditSettingchaged();
    }
    insightView->ImsightSettingchaged();
}

void MainWindow::on_actionAbout_triggered()
{
    AboutDialog* dlgAbout = new AboutDialog(this);
    dlgAbout->exec();
}

void MainWindow::on_actionBarChart_triggered()
{
    QString strText;
    if (m_nView == 1)
    {
        strText = tr("[UDF]");

    }
    else {
        strText = tr("[PDXP]");
    }
    m_pChartView->m_nView = m_nView;
    DataView* view = dynamic_cast<DataView*>(tab->widget(m_nTab));
    QString sFile = view->getFile().fileName();
    m_pChartView->DataInit(sFile, ChartView::Orientation::BARCHART_VIEW);
    tab->setCurrentIndex(tab->addTab(m_pChartView, strText + tr("Frames Info")));
}

void MainWindow::on_actionLineChart_triggered()
{
    QString strText;
    if (m_nView == 1)
    {
        strText = tr("[UDF]");
    }
    else {
        strText = tr("[PDXP]");
    }
    m_pChartView->m_nView = m_nView;
    DataView* view = dynamic_cast<DataView*>(tab->widget(m_nTab));
    QString sFile = view->getFile().fileName();
    m_pChartView->DataInit(sFile, ChartView::Orientation::LINECHART_VIEW);
    tab->setCurrentIndex(tab->addTab(m_pChartView, strText + tr("Frame Rate Info")));
}


void MainWindow::on_actionSplineChart_triggered()
{
    QString strText;
    if (m_nView == 1)
    {
        strText = tr("[UDF]");
    }
    else {
        strText = tr("[PDXP]");
    }
    m_pChartView->m_nView = m_nView;
    DataView* view = dynamic_cast<DataView*>(tab->widget(m_nTab));
    QString sFile = view->getFile().fileName();
    m_pChartView->DataInit(sFile, ChartView::Orientation::SPLINE_VIEW);
    tab->setCurrentIndex(tab->addTab(m_pChartView, strText + tr("Normal analysis curve")));
}


void MainWindow::saveAsTriggered()
{
    if (DataView* view = dynamic_cast<DataView*>(tab->currentWidget())) {
        view->savaAs();
    }
}

void MainWindow::undoTriggered()
{
    if (DataView* view = dynamic_cast<DataView*>(tab->currentWidget())) {
        view->undo();
    }
}

void MainWindow::redoTriggered()
{
    if (DataView* view = dynamic_cast<DataView*>(tab->currentWidget())) {
        view->redo();
    }
}

